using System.Text.RegularExpressions;
using MultiAgentsShared;
using MultiAgentsClient.Shared;
using OpenAI.ObjectModels.RequestModels;
using System.Text;
using System.Runtime.CompilerServices;

#if BACKEND
using File = MultiAgentsServer.Scripts.Services.FileOperationService;
#endif

namespace MultiAgentsClient.ChatDataStructures;

[Serializable]
public class ChatListContainer
{
    public List<ChatMessageData> ChatList = [];

    public ChatListContainer() { }
}

#if BACKEND
public static class ChatListContainerExtension
{
    private static readonly object fileLock = new();
    public static void LogMessages(this List<ChatMessageData> chatMessages, string? response, string? toolCalls)
    {
        lock (fileLock)
        {
            // Get the path to the Documents directory
            string documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            // Define the path to the log file
            string logFilePath = Path.Combine(documentsDirectory, @"MultiAgents\log_message.txt");

            // Use StringBuilder for efficient string concatenation
            StringBuilder logMessageBuilder = new StringBuilder();

            logMessageBuilder.AppendLine("# History messages:");

            // Append chat messages to the log, wrapping content in code blocks
            foreach (ChatMessageData messageData in chatMessages)
            {
                logMessageBuilder.AppendLine($"### {messageData.role}:");
                logMessageBuilder.AppendLine("##### Content:");
                logMessageBuilder.AppendLine("```markdown");
                logMessageBuilder.AppendLine(messageData.content ?? "!!NULL!!");
                logMessageBuilder.AppendLine("```");
                logMessageBuilder.AppendLine();

                if (messageData.toolCalls != null)
                {
                    logMessageBuilder.AppendLine("##### ToolCalls:");
                    foreach (var toolCall in messageData.toolCalls)
                    {
                        logMessageBuilder.AppendLine("```markdown");
                        logMessageBuilder.AppendLine(toolCall.ToString());
                        logMessageBuilder.AppendLine("```");
                    }

                    logMessageBuilder.AppendLine();
                }
            }

            logMessageBuilder.AppendLine();
            logMessageBuilder.AppendLine("# RESPONSE:");
            logMessageBuilder.AppendLine("```markdown");
            logMessageBuilder.AppendLine(response ?? "!!NULL!!");
            logMessageBuilder.AppendLine("```");
            logMessageBuilder.AppendLine();
            logMessageBuilder.AppendLine("### TOOLCALLS:");
            logMessageBuilder.AppendLine("```markdown");
            logMessageBuilder.AppendLine(toolCalls ?? "NULL");
            logMessageBuilder.AppendLine("```");
            logMessageBuilder.AppendLine();

            // Convert the log message to a string
            string logMessage = logMessageBuilder.ToString();

            // Ensure the directory exists
            Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));

            // Append the log message to the log file
            File.CreateFile(logFilePath, logMessage);
        }
    }
}
#endif

public static class ChatStringExtension
{
    public static string NameAsSystemReadable(string userName)
    {
        // Step 1: Replace spaces with underscores
        string modifiedUsername = userName.Replace(" ", "_");
        modifiedUsername = modifiedUsername.Replace(",", "_AND_");

        // Step 2: Remove disallowed characters
        modifiedUsername = Regex.Replace(modifiedUsername, "[^a-zA-Z0-9_\u4e00-\u9fff]", "");

        // Step 3: Truncate to 64 characters if necessary
        if (modifiedUsername.Length > 64)
        {
            modifiedUsername = modifiedUsername[..64];
        }

        return modifiedUsername;
    }

    public static List<LlmMessageSimp> ChatListHistoryLlmSimp(this ChatAgent chatAgent)
    {
        var returnVal = new List<LlmMessageSimp>();
        var chatListOrderedByTime = chatAgent.ChatListContainer.ChatList.OrderBy(c => c.TimeAdded).ToList();
        foreach (var chat in chatListOrderedByTime)
        {
            var messageContent = chat.content + "\n";

            if (chat.toolCalls != null)
            {
                foreach (var toolCall in chat.toolCalls)
                {
                    messageContent += $"{{Try to make Tool-Call -> {toolCall.FunctionCall.Name}}}\n";
                }
            }

            returnVal.Add(new LlmMessageSimp(chat.role, messageContent));
        }

        return returnVal;
    }

    public static string ChatListHistory(this ChatAgent chatAgent, int shortenHistoryContentTo = -1)
    {
        var lastMsgFirstChatList = chatAgent.ChatListContainer.ChatList.OrderByDescending(c => c.TimeAdded).ToList();
        var chatListString = "\n";

        chatListString += "\n~~~~~~~~~~~~~~~(Chat History)~~~~~~~~~~~\n";

        chatListString += "{\n";
        for (int i = 1; i < lastMsgFirstChatList.Count(); i++)
        {
            var chat = lastMsgFirstChatList[i];
            chatListString += $"    {{ [{chat.role}] | [{chat.TimeAdded}]: ";
            chatListString += $"Message From {chat.author}:\n";

            if (shortenHistoryContentTo < 0)
            {
                chatListString += $" {chat.content}";
            }
            else
            {
                string[] words = chat.content.Split(' '); // Splitting the sentence into words
                int numberOfWords = Math.Min(words.Length, shortenHistoryContentTo); // Take the first 10 words or the total number of words if less than 10
                string shortContent = string.Join(" ", words, 0, numberOfWords); // Joining the first 5 to 10 words back into a sentence
                shortContent = shortContent.Replace("\n", "");

                chatListString += $" {shortContent}... ";
            }


            if (chat.toolCalls != null)
            {
                foreach (var toolCall in chat.toolCalls)
                {
                    chatListString += $"{{FuncCall -> {toolCall.FunctionCall.Name}}}, ";
                }
            }

            chatListString += "    },\n";
        }

        chatListString += "};\n";

        return chatListString;
    }
}
